iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0
Software Development

程式淨化計畫:痛苦是重構的起源!系列 第 25

Replace Type Code with Class 的重構

  • 分享至 

  • xImage
  •  

Replace Type Code with Class

簡介

原因: 欄位使用int、string等的類型, 無法保護它不受不正確的賦值和非法的等同性比較
解法: 把欄位的類型宣告為類別, 從而限制賦值和同等性比較

重構前範例

假設有個SystemPermission類別, 裡面有定義權限的常數REQUESTED, CLAIMED, DENIEDGRANTED
而有一個_state欄位儲存目前的權限值. 並提供Claimed(), Denied()Granted()函數做權限值的改變.

public class SystemPermission
{
    private bool _granted;
    private string _state;
    public static readonly string REQUESTED = "REQUESTED";
    public static readonly string CLAIMED = "CLAIMED";
    public static readonly string DENIED = "DENIED";
    public static readonly string GRANTED = "GRANTED";

    public string State
    {
        get => _state;
        private set => _state = value;
    }

    public SystemPermission()
    {
        State = REQUESTED;
        _granted = false;
    }

    public void Claimed()
    {
        if (State == REQUESTED)
        {
            State = CLAIMED;
        }
    }

    public void Denied()
    {
        if (State == CLAIMED)
        {
            State = DENIED;
        }
    }

    public void Granted()
    {
        if (State != CLAIMED)
        {
            return;
        }

        State = GRANTED;
        _granted = true;
    }

    public bool IsGranted()
    {
        return _granted;
    }
}

重構後範例

將前面的權限常數, 轉成PermissionState類別

  1. 宣告static readonly
  2. 代入所需識別值, 這範例是name字串

SystemPermission_state欄位從字串改成PermissionState物件.
後續的比較以reference object的比較.

public class PermissionState
{
    private readonly string _name;
    public PermissionState(string name)
    {
        _name = name;
    }

    public override string ToString()
    {
        return _name;
    }

    public static readonly PermissionState REQUESTED = new PermissionState("REQUESTED");
    public static readonly PermissionState CLAIMED = new PermissionState("CLAIMED");
    public static readonly PermissionState DENIED = new PermissionState("DENIED");
    public static readonly PermissionState GRANTED = new PermissionState("GRANTED");
}

public class SystemPermission
{
    private bool _granted;

    public PermissionState State
    {
        get => _permission;
    }

    private PermissionState Permission
    {
        set => _permission = value;
    }

    private PermissionState _permission;

    public SystemPermission()
    {
        Permission = PermissionState.REQUESTED;
        _granted = false;
    }

    public void Claimed()
    {
        if (State == PermissionState.REQUESTED)
        {
            Permission = PermissionState.CLAIMED;
        }
    }

    public void Denied()
    {
        if (State == PermissionState.CLAIMED)
        {
            Permission = PermissionState.DENIED;
        }
    }

    public void Granted()
    {
        if (State != PermissionState.CLAIMED)
        {
            return;
        }

        Permission = PermissionState.GRANTED;
        _granted = true;
    }

    public bool IsGranted()
    {
        return _granted;
    }
}

重構的好處

  1. 更好地避免非法賦值和比較
  2. 減少typo造成的bug

重構的壞處

  1. 比使用不安全類型要求更多的程式碼

上一篇
Introduce Null Object 的重構
下一篇
Clean Code - Chapter 12 Emergence(嶄露頭角)
系列文
程式淨化計畫:痛苦是重構的起源!31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言